#ifndef STRATUM_SOCKET_H
#define STRATUM_SOCKET_H
#include "stratum.h"
#include "client.h"

#define STRATUM_SOCKET_BUFF_SIZE (2*1024)

class StratumSocket {
public:
    StratumSocket(int sock);
    StratumSocket(StratumSocket& that);
    ~StratumSocket();
    bool connected();
    void realIp();
public:
    char m_ip[64];
    int m_port;
    int m_sock;
    int m_buff_len;
    char m_buff[STRATUM_SOCKET_BUFF_SIZE];
    int m_last_read;
    int m_total_read;
};


StratumSocket* socketInitialize(int sock);
void socketClose(StratumSocket*  s);
json_value* socketNextJson(StratumSocket* s, StratumClient* client=nullptr);
int socketSend(StratumSocket* s, const char* format, ...);
int socketSendRaw(StratumSocket* s, const char* buffer, int size);

static union {
    struct {
        char line[108];
    } v1;
    struct {
        uint8_t sig[12];
        uint8_t ver_cmd;
        uint8_t fam;
        uint16_t len;
        union {
            struct {  /* for TCP/UDP over IPv4, len = 12 */
                uint32_t src_addr;
                uint32_t dst_addr;
                uint16_t src_port;
                uint16_t dst_port;
            } ip4;
            struct {  /* for TCP/UDP over IPv6, len = 36 */
                uint8_t  src_addr[16];
                uint8_t  dst_addr[16];
                uint16_t src_port;
                uint16_t dst_port;
            } ip6;
            struct {  /* for AF_UNIX sockets, len = 216 */
                uint8_t src_addr[108];
                uint8_t dst_addr[108];
            } unx;
        } addr;
    } v2;
} hdr;

#endif //STRATUM_SOCKET_H
